package com.example.springboot_springsecurity_jwt_redis.utils;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;

import java.util.HashMap;
import java.util.Set;
import java.util.concurrent.TimeUnit;

/**
 * redis是键值对数据库
 * 我们使用java提供的模板工具类，我们就可以直接操作redis,存取token
 */

@Component
//@PropertySource(value = "classpath:application.yml")
public class RedisUtil {

    // 从application.yml引入token过期秒数
    @Value("${token.expirationSeconds}")
    private int expirationSeconds;
    // 从application.yml引入有效时间
    @Value("${token.validTime}")
    private int validTime;

    //创建redis模板
    @Autowired
    private StringRedisTemplate redisTemplate;

    //构造
    public RedisUtil() {
    }


    /**
     * 获取所有的键
     * @param key
     * @return
     */
    public Set<String> keys(String key) {
        return this.redisTemplate.keys(key);
    }

    /**
     * 通过键名，获取键值对象
     * @param key
     * @return
     */
    public Object get(String key) {
        return this.redisTemplate.opsForValue().get(key);
    }

    /**
     * 存键值对象
     * @param key
     * @param value
     */
    public void set(String key, String value) {
        this.redisTemplate.opsForValue().set(key, value, 7200L, TimeUnit.SECONDS);
    }

    /**
     * 存键值对象
     * @param key
     * @param value
     * @param expire 时间(秒) expire要大于0 如果expire小于等于0 将设置无限期
     */
    public void set(String key, String value, Integer expire) {
        this.redisTemplate.opsForValue().set(key, value, (long)expire, TimeUnit.SECONDS);
    }

    /**
     * 删除键值，即token
     * @param key
     */
    public void delete(String key) {
        this.redisTemplate.opsForValue().getOperations().delete(key);
    }

    /**
     * HashSet
     * 向一张hash表中放入数据,如果不存在将创建
     * @param key   键
     * @param filed     值
     * @param domain
     */
    public void hset(String key, String filed, Object domain) {
        this.redisTemplate.opsForHash().put(key, filed, domain);
    }

    /**
     *
     * @param key
     * @param filed
     * @param domain
     * @param expire 如果已存在的hash表有时间,这里将会替换原有的时间
     */
    public void hset(String key, String filed, Object domain, Integer expire) {
        this.redisTemplate.opsForHash().put(key, filed, domain);
        this.redisTemplate.expire(key, (long)expire, TimeUnit.SECONDS);
    }

    /**
     * hashSet
     * @param key   键
     * @param hm    多个键值
     */
    public void hset(String key, HashMap<String, Object> hm) {
        this.redisTemplate.opsForHash().putAll(key, hm);
    }


    public void hsetAbsent(String key, String filed, Object domain) {
        this.redisTemplate.opsForHash().putIfAbsent(key, filed, domain);
    }

    /**
     *
     * @param key
     * @param field
     * @return
     */
    public Object hget(String key, String field) {
        return this.redisTemplate.opsForHash().get(key, field);
    }

    public Object hget(String key) {
        return this.redisTemplate.opsForHash().entries(key);
    }

    /**
     * 删除缓存键值对
     * @param key
     */
    public void deleteKey(String key) {
        this.redisTemplate.opsForHash().getOperations().delete(key);
    }


    public Boolean hasKey(String key, String field) {
        return this.redisTemplate.opsForHash().hasKey(key, field);
    }

    /**
     * 判断key是否存在
     * @param key
     * @return
     */
    public Boolean hasKey(String key) {
        return this.redisTemplate.opsForHash().getOperations().hasKey(key);
    }

    /**
     * 判断 token 是否在黑名单内
     * @param token
     * @return
     */
    public Boolean isBlackList(String token) {
        return this.hasKey("blacklist", token);
    }

    /**
     * 将 token 添加人黑名单
     * @param token
     */
    public void addBlackList(String token) {
        this.hset("blacklist", token, "true");
    }

    /**
     *
     * @param token
     * @return
     */
    public Object getTokenValidTimeByToken(String token) {
        return this.redisTemplate.opsForHash().get(token, "tokenValidTime");
    }

    /**
     * 通过 token 获取实体名
     * @param token
     * @return
     */
    public Object getUsernameByToken(String token) {
        return this.redisTemplate.opsForHash().get(token, "username");
    }

    /**
     * 根据 token 获取ip
     * @param token
     * @return
     */
    public Object getIPByToken(String token) {
        return this.redisTemplate.opsForHash().get(token, "ip");
    }

    /**
     * 通过 token 获取超时时间
     * @param token
     * @return
     */
    public Object getExpirationTimeByToken(String token) {
        return this.redisTemplate.opsForHash().get(token, "expirationTime");
    }

    /**
     * 设置 token 的过期时间、有效时间、实体、ip
     * @param token
     * @param username
     * @param ip
     */
    public void setTokenRefresh(String token, String username, String ip) {
        Integer expire = this.validTime * 24 * 60 * 60 * 1000;
        this.hset(token, "tokenValidTime", DateUtil.getAddDayTime(this.validTime), expire);
        this.hset(token, "expirationTime", DateUtil.getAddDaySecond(this.expirationSeconds), expire);
        this.hset(token, "username", username, expire);
        this.hset(token, "ip", ip, expire);
    }
}
